package ft.esc.impl;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import javafx.application.Application;
import javafx.application.Platform;

import ft.esc.itf.IStringCallBack;
import ft.esc.util.UFM;
import ft.esc.impl.trav.DirFileTravWithCb;

/**
 * Send Files in a New Thread.<br />
 * The Working Thread
 */
public class FileSendClientImpl implements Runnable
{
	private String remoteHost = "";
	private int remotePort = 0;
	private String filePath = "";
	private List<Map<String, String>> al_ctx = null;

	private EchoSocketClientController _ctx = null;
	
	public FileSendClientImpl(String remoteHost, String remotePort, String filePath, List<Map<String, String>> ctx )
	{
		this.remoteHost = remoteHost;
		this.filePath = filePath;
		if (ctx != null) {
			this.al_ctx = ctx;
		} else {
			this.al_ctx = new ArrayList<Map<String, String>>(256);
		}


		try {
			this.remotePort = Integer.parseInt(remotePort);
		} catch (Exception e) {
		}
	}
	
	public void setCtx(EchoSocketClientController ctx)
	{
		_ctx = ctx;
	}
	
	public void run()
	{
		OutputStream os = null;
		InputStream is = null;
		Socket socket = null;
		byte[] buf = null;

		List<Map<String, String>> al = null;

		try
		{
			al = getFilesWithCb(filePath);
			
			// 2019-06-07 增加 // 按照 文件名 排序
//			al = fooSort(al);
			 
			// 并且反转一下
//			al = fooInverse(al);

			if(al!=null && al.size()>0 && _ctx!=null)
			{
				final List<Map<String,String>> ffal = al;
//				System.out.println("已取得待发送文件" +
//						Integer.toString(al.size()) + "个");
				
				final EchoSocketClientController ffctx = _ctx;
				Platform.runLater(new Runnable() {
					public void run() {
						ffctx.postStr("已取得待发送文件" +
								Integer.toString(ffal.size()) + "个");
					}
				});
			}

//				try
//				{
//					is = new FileInputStream(filePath);
//				}
//				catch(FileNotFoundException e)
//				{
//					{
//						Message me0 = mHandler.obtainMessage();
//						me0.what = MSG_PRINT;
//						me0.obj = (Object)"文件"+filePath+"不存在";
//						me0.sendToTarget();
//					}
//				}

			socket = new Socket(remoteHost, remotePort);

			if (socket.isConnected())
			{
				os = socket.getOutputStream();

				DataOutputStream dos = null;
				dos = new DataOutputStream(os);

				// 读取文件发送至 Socket 的缓冲
				buf = new byte[512];

				// 发送文件总数
				dos.writeInt(al.size());

				// 循环，从 al 中取出一个个的文件，并打开
				for (int i = 0; i < al.size(); i++)
				{
					Map<String, String> m = al.get(i);

					// 将文件置入返回结果
					al_ctx.add(m);

					String path = m.get(C.AL_CTX_NAME);
//					String lens = m.get(AL_CTX_LENGTH);

					// DEBUG
//					System.out.println("正试图发送文件：" + path);
					
					if(path!=null && path.length()>0 && _ctx!=null)
					{
						final String ff_path = path;
						
						final EchoSocketClientController ffctx = _ctx;
						Platform.runLater(new Runnable() {
							public void run() {
								ffctx.postStr("正试图发送文件：" + ff_path);
							}
						});
					}
					
					try
					{
						is = new FileInputStream(path);
					}
					catch(FileNotFoundException e)
					{
//						{
//							Message me0 = mHandler.obtainMessage();
//							me0.what = MSG_PRINT;
//							me0.obj = (Object) "文件" + path + "不存在";
//							me0.sendToTarget();
//						}

						System.out.println("文件" + path + "不存在");
					}

					dos.writeUTF(path);
					dos.writeLong(is.available());

					int ch = 0;

					ch = is.read(buf, 0, buf.length);
					while (ch != -1) {
						//dos.writeByte(ch);
						dos.write(buf, 0, ch);
						ch = is.read(buf);
					}
					
					is.close();
					// DEBUG
//					System.out.println("第"+Integer.toString(1+i)+"个文件发送完毕。");
				}

//					dos.writeUTF(filePath);
//					dos.writeLong(is.available());

//					int ch = 0; //is.read();

//					byte[] buf = new byte[512];
//					ch = is.read(buf);
//
//					while(ch!=-1)
//					{
//						//dos.writeByte(ch);
//						dos.write(buf, 0, ch);
//						ch = is.read(buf);
//					}

				is = null;
				
				dos.flush();
				dos.close();
				os.close();
				socket.close();

				// 已改成手动选择，不需要自行删除文件了。
//					{
//						// 最后删除文件
//						File f = new File(filePath);
//						if(f!=null && f.isFile() && f.canWrite())
//						{
//							f.delete();
//						}
//					}
			}
		} catch (Exception e) {
//			{
//				Message me0 = mHandler.obtainMessage();
//				me0.what = MSG_PRINT;
//				me0.obj = (Object) "发送至"
//						+ remoteHost + ":" + Integer.toString(remotePort)
//						+ "出错\n"
//						+ e.getMessage();
//				me0.sendToTarget();
//			}
			System.out.println("发送至"+ remoteHost + ":" + Integer.toString(remotePort)+ "出错");
			System.out.println(e.getMessage());
		}

//		// 执行完毕，通知主线程可以取ctx了。
//		{
//			Message me0 = mHandler.obtainMessage();
//			me0.what = MSG_RETURN_AL_CTX;
//			me0.obj = al_ctx;
//			me0.sendToTarget();
//		}

//		System.out.println("所有文件发送完毕，线程即将退出。");
		if(_ctx!=null)
		{
			final EchoSocketClientController ffctx = _ctx;
			final String str_msg = "所有文件发送完毕，线程即将退出。";
			Platform.runLater(new Runnable() {
				public void run() {
//					System.out.println(ffctx == null);
//					System.out.println(str_msg == null);
					ffctx.postStr(str_msg);
					
					// 撤销按钮失效
					ffctx.showEditControls();
				}
			});
		}
		else
		{
			System.out.println("新线程中，_ctx为空！");
		}
		
		if(_ctx!=null)
		{
			_ctx = null;
		}
	}
	
	private List<Map<String,String>> getFilesWithCb(String filePath)
	{
		final List<Map<String, String>> al = new ArrayList<Map<String,String>>();
		
		DirFileTravWithCb r = new DirFileTravWithCb();
		r.addFaLst(filePath);
		r.setCallBack(new IStringCallBack()
		{
			@Override
			public void processData(String str)
			{
				if(str!=null && str.length()>0)
				{
					Map<String,String> m = null;
					m = UFM.getFileInfoMapByPath(str);
					al.add(m);
				}
			}
		});
		
		
		r.startRun();
		
		
		return al;
	}
	
	/**
	 * 根据给定的 filePath 返回 Map 包含 name, length
	 * @param filePath
	 * @return
	 */
	private List<Map<String, String>> getFiles(String filePath)
	{
		List<Map<String, String>> al = null;

		if (filePath != null && filePath.length() > 0) {
			File f = new File(filePath);
			if (f != null && f.exists() && f.isFile() && f.canRead()) {
				al = new ArrayList<Map<String, String>>();

				// 取得文件
				long len = f.length();

				{
					Map<String, String> m = new HashMap<String, String>();
					m.put(C.AL_CTX_NAME, filePath);
					m.put(C.AL_CTX_LENGTH, Long.toString(len));
					al.add(m);
				}
			} else if (f != null && f.exists() && f.isDirectory()) {
				// 遍历目录
				String[] files = f.list();
				if (files != null && files.length > 0) {
					al = new ArrayList<Map<String, String>>(files.length);

					for (int i = 0; i < files.length; i++) {
						File fp = new File(filePath, files[i]);

						if (fp != null && fp.exists() && fp.isFile() && fp.canRead()) {
							String path = null;
							if (filePath.charAt(filePath.length() - 1) == '/') {
								path = filePath + files[i];
							} else {
								path = filePath + "/" + files[i];
							}

							long lens = fp.length();

							{
								Map<String, String> m = new HashMap<String, String>();
								m.put(C.AL_CTX_NAME, path);
								m.put(C.AL_CTX_LENGTH, Long.toString(lens));
								al.add(m);
							}

						}


					}
				}
			}
		}
		return al;
	}
	
	private static List<Map<String,String>> fooSort(List<Map<String,String>> al)
	{
		List<Map<String,String>> ret = al;
		
		if(al!=null && al.size()>1)
		{
			List<Map<String,String>> myRet = new ArrayList<Map<String,String>>( 1 + al.size() );
			
			// 路径与 Map 之间的映射关系
			Map<String,Map<String,String>> mm = new HashMap<String,Map<String,String>>( 1 + al.size() );
			
			// 用于路径排序的 Set
			Set<String> ss = new TreeSet<String>();
			
			for(int i=0; i<al.size(); i++)
			{
				
				Map<String,String> m = al.get(i);
				String path = m.get(C.AL_CTX_NAME);
				
				if(mm.containsKey(path))
				{
					System.out.print("错误！已存在重复的文件名：[");
					System.out.print( path );
					System.out.println("]");
				}
				else
				{
					mm.put(path, m);
					
					ss.add(path);
				}
				
			}
			
			// 遍历 ss 取出排序后的路径
			for(String sp : ss)
			{
				Map<String,String> sm = mm.get(sp);
				myRet.add(sm);
			}
			
			if(myRet!=null && myRet.size()>0)
			{
				ret = myRet;
			}
		}
		return ret;
	}
	
	private static List<Map<String,String>> fooInverse(List<Map<String,String>> al)
	{
		List<Map<String,String>> ret = al;
		
		int am = al.size();
		if(al!=null && am>1)
		{
			List<Map<String,String>> myRet = new ArrayList<Map<String,String>>( 1 + am );
			
			for(int i=0; i<am; i++)
			{
				Map<String,String> m = al.get(am -i -1);
				myRet.add(m);
			}
			
			if(myRet!=null && myRet.size()>0)
			{
				ret = myRet;
			}
		}
		
		return ret;
	}
}
